/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.MaintainPlanWeeklyReportProjectPageDTO;
import org.springblade.modules.admin.dto.WeeklyReportRepairListPageDTO;
import org.springblade.modules.admin.dto.WeeklyReportRescueListPageDTO;
import org.springblade.modules.admin.entity.MaintainPlanWeeklyReport;
import org.springblade.modules.admin.enums.MaintainPlanContentEnum;
import org.springblade.modules.admin.enums.TaskStatusEnum;
import org.springblade.modules.admin.service.IMaintainPlanWeeklyReportService;
import org.springblade.modules.admin.vo.MaintainPlanWeeklyReportProjectDetailVO;
import org.springblade.modules.admin.vo.MaintainPlanWeeklyReportProjectPageVO;
import org.springblade.modules.admin.vo.WeeklyReportRepairListPageVO;
import org.springblade.modules.admin.vo.WeeklyReportRescueListPageVO;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * 任务周报 控制器
 *
 * @author lsay
 * @since 2024-09-02
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/maintain/plan/weekly/report")
@Api(value = "任务周报", tags = "任务周报接口")
public class MaintainPlanWeeklyReportController extends BladeController {

	private final IMaintainPlanWeeklyReportService maintainPlanWeeklyReportService;

	@TenantIgnore
	@GetMapping("/gen")
	public R<Boolean> gen(String weekBeginTime,String weekEndTime) {
		return R.data(maintainPlanWeeklyReportService.generatePlanWeeklyReport(weekBeginTime,weekEndTime));
	}

	/**
	 * 维保报告管理端分页列表
	 * 根据项目分页
	 */
	@PostMapping("/project/page")
	@ApiOperationSupport(order = 30)
	@ApiOperation(value = "维保报告管理端分页列表", notes = "传入maintainPlanWeeklyReportPageDTO")
	public R<IPage<MaintainPlanWeeklyReportProjectPageVO>> maintainPlanWeeklyReportPage(@RequestBody @Valid MaintainPlanWeeklyReportProjectPageDTO maintainPlanWeeklyReportPageDTO) {
		Query query = maintainPlanWeeklyReportPageDTO.getQuery();
		IPage<MaintainPlanWeeklyReportProjectPageVO> result = maintainPlanWeeklyReportService.maintainPlanWeeklyReportPage(Condition.getPage(query), maintainPlanWeeklyReportPageDTO);
		return R.data(result);
	}


	/**
	 * 根据周报id获取详情
	 */
	@GetMapping("/detail/view")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入maintainPlanWeeklyReport")
	public R<MaintainPlanWeeklyReport> detail(MaintainPlanWeeklyReport weeklyReport) {
		return R.data(maintainPlanWeeklyReportService.selectDetail(weeklyReport));
	}

	/**
	 * 重点关注
	 * @param buildingId
	 * @return
	 */
	@GetMapping("/emp/elevator")
	public R<List<Map<String,Object>>> empElevatorList(Long buildingId,Integer typeStatus,Integer status,
													   String startTime,String endTime){
		return R.data(maintainPlanWeeklyReportService.empElevatorList(buildingId,typeStatus,status,startTime,endTime));
	}

	/**
	 * 根据周报id获取详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 31)
	@ApiOperation(value = "根据周报id获取详情", notes = "传入maintainPlanWeeklyReportId")
	public R<MaintainPlanWeeklyReportProjectDetailVO> maintainPlanWeeklyReportDetail(Long reportId) {
		MaintainPlanWeeklyReportProjectDetailVO result = maintainPlanWeeklyReportService.maintainPlanWeeklyReportDetail(reportId);
		return R.data(result);
	}

	/**
	 * 维保明细维修工单列表
	 */
	@PostMapping("/detail/repair/plan/list")
	@ApiOperationSupport(order = 32)
	@ApiOperation(value = "维保明细维修工单列表", notes = "传入maintainPlanWeeklyReportId")
	public R<IPage<WeeklyReportRepairListPageVO>> planViewRepairListPage(@RequestBody @Valid WeeklyReportRepairListPageDTO weeklyReportRepairListPageDTO) {
		Query query = weeklyReportRepairListPageDTO.getQuery();
		IPage<WeeklyReportRepairListPageVO> pages = maintainPlanWeeklyReportService.planViewRepairListPage(Condition.getPage(query), weeklyReportRepairListPageDTO);
		return R.data(pages);
	}

	/**
	 * 维保明细救援工单列表
	 */
	@PostMapping("/detail/rescue/plan/list")
	@ApiOperationSupport(order = 33)
	@ApiOperation(value = "维保明细救援工单列表", notes = "传入maintainPlanWeeklyReportId")
	public R<IPage<WeeklyReportRescueListPageVO>> planViewRescuePage(@RequestBody @Valid WeeklyReportRescueListPageDTO weeklyReportRescueListPageDTO) {
		Query query = weeklyReportRescueListPageDTO.getQuery();
		IPage<WeeklyReportRescueListPageVO> pages = maintainPlanWeeklyReportService.planViewRescuePage(Condition.getPage(query), weeklyReportRescueListPageDTO);
		return R.data(pages);
	}

	/**
	 * 维保明细维修工单excel下载
	 */
	@PostMapping("/detail/repair/plan/excel")
	@ApiOperationSupport(order = 34)
	@ApiOperation(value = "维保明细维修工单excel下载")
	public void planViewRepairListExcel(HttpServletResponse response, @RequestBody @Valid WeeklyReportRepairListPageDTO weeklyReportRepairListPageDTO) throws IOException {
		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList
				("项目名称", "电梯名称", "故障描述", "故障原因", "任务状态", "实际执行人","报障时间","签到时间（第1个）", "完成时间");
			rows.add(title);
			Query query = weeklyReportRepairListPageDTO.getQuery();
			query.setCurrent(1);
			query.setSize(Integer.MAX_VALUE);
			IPage<WeeklyReportRepairListPageVO> pages = maintainPlanWeeklyReportService.planViewRepairListPage(Condition.getPage(query), weeklyReportRepairListPageDTO);
			List<WeeklyReportRepairListPageVO> records = pages.getRecords();
			for (WeeklyReportRepairListPageVO repairListVo : records) {
				List<String> row = new ArrayList<>(9);
				row.add(Convert.toStr(repairListVo.getBuildingName()));
				row.add(Convert.toStr(repairListVo.getElevatorAddress()));
				row.add(Convert.toStr(repairListVo.getMfDesc()));
				row.add(Convert.toStr(repairListVo.getFaultCauseDesc()));
				row.add(Convert.toStr(TaskStatusEnum.getTaskName(MaintainPlanContentEnum.MAINTAIN_WX.getId(), repairListVo.getStatus())));
				row.add(Convert.toStr(repairListVo.getExecutors()));
				Date createTime = repairListVo.getCreateTime();
				if(createTime!= null){
					row.add(DateUtil.format(createTime, "yyyy-MM-dd HH:mm:ss"));
				}else{
					row.add("");
				}
				Date firstSignTime = repairListVo.getFirstSignTime();
				if(firstSignTime!= null){
					row.add(DateUtil.format(firstSignTime, "yyyy-MM-dd HH:mm:ss"));
				}else{
					row.add("");
				}
				Date finishTime = repairListVo.getFinishTime();
				if(finishTime!= null){
					row.add(DateUtil.format(finishTime, "yyyy-MM-dd HH:mm:ss"));
				}else{
					row.add("");
				}
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (Exception e) {
			log.info(e.getMessage());
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}
	}

	/**
	 * 维保明细救援工单excel下载
	 */
	@PostMapping("/detail/rescue/plan/excel")
	@ApiOperationSupport(order = 35)
	@ApiOperation(value = "维保明细救援工单excel下载", notes = "传入maintainPlanWeeklyReportId")
	public void planViewRescueListExcel(HttpServletResponse response, @RequestBody @Valid WeeklyReportRescueListPageDTO weeklyReportRescueListPageDTO) throws IOException {
		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList
				("项目名称", "电梯名称", "任务状态", "报障时间", "救援用时（到达/未达）", "实际执行人", "签到时间（第1个）", "完成时间");
			rows.add(title);
			Query query = weeklyReportRescueListPageDTO.getQuery();
			query.setCurrent(1);
			query.setSize(Integer.MAX_VALUE);
			IPage<WeeklyReportRescueListPageVO> pages = maintainPlanWeeklyReportService.planViewRescuePage(Condition.getPage(query), weeklyReportRescueListPageDTO);
			List<WeeklyReportRescueListPageVO> records = pages.getRecords();
			for (WeeklyReportRescueListPageVO rescueListVo : records) {
				List<String> row = new ArrayList<>(16);
				row.add(Convert.toStr(rescueListVo.getBuildingName()));
				row.add(Convert.toStr(rescueListVo.getElevatorAddress()));
				row.add(Convert.toStr(TaskStatusEnum.getTaskName(MaintainPlanContentEnum.MAINTAIN_KR.getId(),TaskStatusEnum.JY_RESCUE.getStatus())));
				Date createTime = rescueListVo.getCreateTime();
				if(createTime!= null){
					row.add(DateUtil.format(createTime, "yyyy-MM-dd HH:mm:ss"));
				}else{
					row.add("");
				}
				row.add(Convert.toStr(rescueListVo.getArrivalTimeDesc()));
				row.add(Convert.toStr(rescueListVo.getExecutors()));
				Date arrivalTime = rescueListVo.getArrivalTime();
				if(arrivalTime != null){
					row.add(DateUtil.format(arrivalTime, "yyyy-MM-dd HH:mm:ss"));
				}else {
					row.add("");
				}
				Date finishTime = rescueListVo.getFinishTime();
				if(!Func.isNull(finishTime)){
					row.add(DateUtil.format(finishTime, "yyyy-MM-dd HH:mm:ss"));
				}else{
					row.add("");
				}
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (Exception e) {
			log.info(e.getMessage());
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}
	}

	/**
	 * 根据搜素条件返回维修工单视图列表抬头统计
	 */
	@TenantIgnore
	@PostMapping("/repair/plan/list/title/count")
	@ApiOperationSupport(order = 40)
	@ApiOperation(value = "根据搜素条件返回维修工单视图列表抬头统计")
	public R<Map<String, Object>> planViewRepairListTitleCount(@RequestBody WeeklyReportRepairListPageDTO weeklyReportRepairListPageDTO) {
		Query query = new Query();
		query.setCurrent(1);
		query.setSize(Integer.MAX_VALUE);
		weeklyReportRepairListPageDTO.setQuery(query);
		// 清除状态筛选条件
		weeklyReportRepairListPageDTO.setStatusList(new ArrayList<>());
		List<WeeklyReportRepairListPageVO> records = maintainPlanWeeklyReportService.planViewRepairListTitleCount(Condition.getPage(query), weeklyReportRepairListPageDTO);
		Map<String, Object> result = new HashMap<>(3);
		if(!Func.isEmpty(records)){
			long alreadyFinishedCount = records.stream().filter(f -> new Integer(TaskStatusEnum.WX_SIGN_FINISH.getStatus()).equals(f.getStatus())).count();
			long toStartCount = records.stream().filter(f -> new Integer(TaskStatusEnum.WX_TO_START.getStatus()).equals(f.getStatus())).count();
			long underWayCount = records.stream().filter(f -> new Integer(TaskStatusEnum.WX_UNDER_WAY.getStatus()).equals(f.getStatus())).count();
			result.put("toStartCount", toStartCount);
			result.put("underWayCount", underWayCount);
			result.put("finishedCount", alreadyFinishedCount);
			result.put("total", records.size());
			return R.data(result);
		}
		result.put("toStartCount", 0);
		result.put("underWayCount", 0);
		result.put("finishedCount", 0);
		result.put("total", 0);
		return R.data(result);
	}

	/**
	 * 根据搜素条件返回救援工单视图列表抬头统计
	 */
	@PostMapping("/rescue/plan/list/title/count")
	@ApiOperationSupport(order = 41)
	@ApiOperation(value = "根据搜素条件返回救援工单视图列表抬头统计")
	public R<Map<String, Object>> planViewRescueListTitleCount(@RequestBody WeeklyReportRescueListPageDTO weeklyReportRescueListPageDTO) {
		Query query = new Query();
		query.setCurrent(1);
		query.setSize(Integer.MAX_VALUE);
		weeklyReportRescueListPageDTO.setQuery(query);
		List<WeeklyReportRescueListPageVO> records = maintainPlanWeeklyReportService.planViewRescueListTitleCount(Condition.getPage(query), weeklyReportRescueListPageDTO);
		Map<String, Object> result = new HashMap<>(2);
		if(!Func.isEmpty(records)){
			long onTimeCountTotal = records.stream().filter(WeeklyReportRescueListPageVO::getIsOnTime).count();
			result.put("overTimeTotal", records.size() - onTimeCountTotal);
			result.put("onTimeTotal", onTimeCountTotal);
			result.put("total", records.size());
			return R.data(result);
		}
		result.put("overTimeTotal", 0);
		result.put("onTimeTotal", 0);
		result.put("total", 0);
		return R.data(result);
	}

	/**
	 * 功能描述: 发送响应流方法
	 */
	private void setResponseHeader(HttpServletResponse response, String fileName) {
		try {
			try {
				fileName = new String(fileName.getBytes(), "ISO8859-1");
			} catch (UnsupportedEncodingException e) {
				log.info(e.getMessage());
			}
			response.setContentType("application/octet-stream;charset=ISO8859-1");
			response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
			response.addHeader("Pargam", "no-cache");
			response.addHeader("Cache-Control", "no-cache");
		} catch (Exception ex) {
			log.info(ex.getMessage());
		}
	}

}
